home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / cuj1008.zip / RAMEY.ZIP / KEY.C < prev    next >
C/C++ Source or Header  |  1991-10-14  |  7KB  |  243 lines

  1. /*
  2. Copyright (c) Robert Ramey 1991. All Rights Reserved
  3. */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <limits.h>
  8. #include "psort.h"
  9. #include "arg.h"
  10. #include "key.h"
  11.  
  12. #define MAX_KEYS 32
  13. #define NSIZE 16
  14.  
  15. unsigned int key_count = 0;    /* number of keys specified by command line */
  16. KEY key[MAX_KEYS];    /* table of keys specified in command line */
  17.  
  18. size_t
  19.     tab_count = 0,            /* number of fields to count in input record */
  20.     data_offset = 0,        /* start additional data used for sorting */
  21.     *tab = (size_t)NULL,    /* array of pointers to fields */
  22.     record_offset = 1;        /* start of original record data */
  23.  
  24. SEQ *n_seq = (SEQ *)NULL;
  25.  
  26. SEQ *seq;
  27.  
  28. void
  29. key_create(unsigned int, unsigned int, SEQ *, unsigned int,
  30.     unsigned int, BOOLEAN);
  31. void
  32. key_table();
  33. /*********************************************************************
  34. structure for accumulating on keys from information from command line
  35. **********************************************************************/
  36. struct {
  37.     struct {
  38.         BOOLEAN specified;
  39.         int
  40.             start,
  41.             size;
  42.     } field,    /* field specification */
  43.     disp;        /* character displacement specification */
  44.     BOOLEAN    iflag;    /* inverted sequence flag for this field */
  45.     BOOLEAN nflag;    /* key field is a numeric value */
  46.     SEQ *seq;        /* pointer to sequence table */
  47. } key_spec;
  48.  
  49. /*********************************************************************
  50. key_init - initialize information on keys from command line
  51. **********************************************************************/
  52. void
  53. key_init(argc, argv)
  54. unsigned int argc;
  55. char *argv[];
  56. {
  57.     RANGE range;
  58.     unsigned int i, j, l, seq_value, pseq_value;
  59.     int k;
  60.  
  61.     /* set up defaults */
  62.     key_spec.field.specified = FALSE;
  63.     key_spec.field.start = 0;
  64.     key_spec.field.size = 0;
  65.     key_spec.disp.specified = FALSE;
  66.     key_spec.disp.start = 0;
  67.     key_spec.disp.size = UINT_MAX;
  68.     key_spec.seq = (SEQ *)NULL;
  69.     key_spec.nflag = FALSE;
  70.     key_spec.iflag = FALSE;
  71.  
  72.     /* set up default collating sequence */
  73.     /* which consists of printable characters */
  74.     key_spec.seq = (SEQ *)malloc(sizeof(SEQ));
  75.     if(key_spec.seq == (SEQ *)NULL)
  76.         error("Couldn't get space for default collating sequence");
  77.     for(i = 0; i < 256; ++i)
  78.         key_spec.seq->value[i] = 0;
  79.     j = 0;
  80.     for(i = ' '; i <= '~'; ++i)
  81.         key_spec.seq->value[i] = ++j;
  82.     key_spec.seq->order = j;
  83.  
  84.     /* analize arguments in command line */
  85.     for(i = 0; ++i < argc;){
  86.         if(argv[i][0] != '-' || argv[i][2] != '\0'){
  87.             continue;
  88.         }
  89.         switch(argv[i][1]){
  90.         default:
  91.             continue;
  92.         case 'f': case 'F':
  93.             argv[i] = "";
  94.             if(key_spec.field.specified)
  95.                 key_table();
  96.             key_spec.field.specified = TRUE;
  97.             key_spec.disp.start = 0;
  98.             key_spec.disp.size = UINT_MAX;
  99.             arg_range(argv[++i], &range);
  100.             key_spec.field.start = range.start;
  101.             key_spec.field.size = range.end - range.start;
  102.             break;
  103.         case 'c': case 'C':
  104.             argv[i] = "";
  105.             if(key_spec.disp.specified)
  106.                 key_table();
  107.             key_spec.disp.specified = TRUE;
  108.             arg_range(argv[++i], &range);
  109.             if(range.end > range.start)
  110.                 error("Invalid character displacement range");
  111.             key_spec.disp.start = range.start;
  112.             key_spec.disp.size = range.end - range.start + 1;
  113.             break;
  114.         case 'n': case 'N':
  115.             key_spec.nflag = TRUE;
  116.             ++record_offset;
  117.             if(n_seq == (SEQ *)NULL){
  118.                 n_seq = (SEQ *)malloc(sizeof(SEQ));
  119.                 if(n_seq == (SEQ *)NULL)
  120.                     error("Couldn't get space for sign sequence");
  121.                 /* set up collating sequence for - sign */
  122.                 for(j = 0;j < 256;++j)
  123.                     n_seq->value[j++] = 0;
  124.                 j = 0;
  125.                 for(k = -NSIZE; k < 0; ++k)
  126.                     n_seq->value[k & 0xff] = ++j;
  127.                 for(k = 1; k <= NSIZE; ++k)
  128.                     n_seq->value[k & 0xff] = ++j;
  129.                 n_seq->order = j;
  130.             }
  131.             break;
  132.         case 'i': case 'I':
  133.             key_spec.iflag = TRUE;
  134.             break;
  135.         case 'k': case 'K':
  136.             if(i + 1 == argc)
  137.                 break;
  138.             key_spec.iflag = FALSE;
  139.             key_spec.nflag = FALSE;
  140.             key_spec.seq = (SEQ *)malloc(sizeof(SEQ));
  141.             if(key_spec.seq == (SEQ *)NULL)
  142.                 error("Couldn't get space for collating sequence");
  143.             for(j = 0; j < 256 ;++j)
  144.                 key_spec.seq->value[j] = 0;
  145.             key_spec.seq->order = 0;
  146.             if(key_spec.seq == (SEQ *)NULL)
  147.                 error("Couldn't get memory for a sequence table");
  148.             pseq_value = 0;
  149.         case 'r': case 'R':
  150.             argv[i++] = "";
  151.             seq_value = pseq_value;
  152.             while(i < argc && argv[i][0] != NULL && argv[i][0] != '-'){
  153.                 pseq_value = seq_value;
  154.                 arg_range(argv[i], &range);
  155.                 k = range.start < range.end ? +1 : -1;
  156.                 for(j = range.start;;j += k){
  157.                     key_spec.seq->value[j] = ++seq_value;
  158.                     if(j == range.end)
  159.                         break;
  160.                 }
  161.                 argv[i++] = "";
  162.             }
  163.             key_spec.seq->order = seq_value;
  164.             --i;
  165.             continue;
  166.         }
  167.         argv[i] = "";
  168.     }
  169.     /* every sort must have at least one key */
  170.     if(key_count == 0)
  171.         key_table();
  172.  
  173.     tab_count += 2;
  174.     tab = malloc(tab_count * sizeof(int));
  175.     if(tab == (size_t *)NULL)
  176.         error("Couldn't get memory for tab array");
  177.  
  178.     data_offset = sizeof(unsigned int) * (key_count + 1);
  179.     record_offset += data_offset;
  180.  
  181.     return;
  182. }
  183. /*********************************************************************
  184. key_table - create key table entries from command line information
  185. **********************************************************************/
  186. private
  187. void
  188. key_table()
  189. {
  190.     unsigned int i, j;
  191.     int k;
  192.  
  193.     i = key_spec.field.start;
  194.     j = i + key_spec.field.size;
  195.     k  = key_spec.field.size < 0 ? -1 : 1 ;
  196.     tab_count = max(tab_count, i);
  197.     tab_count = max(tab_count, j);
  198.     for(;;){
  199.         if(!key_spec.nflag){
  200.             key_create(key_spec.disp.start, key_spec.disp.size,
  201.                 key_spec.seq, i, DEFAULT, key_spec.iflag);
  202.         }
  203.         else{
  204.             key_create(key_spec.disp.start, 1,
  205.                 n_seq, i, SIGN, key_spec.iflag);
  206.             key_create(key_spec.disp.start, UINT_MAX,
  207.                 key_spec.seq, i, NUMERIC, key_spec.iflag);
  208.             key_create(key_spec.disp.start, UINT_MAX,
  209.                 key_spec.seq, i, FRACTION, key_spec.iflag);
  210.         }
  211.         if(i == j)
  212.             break;
  213.         else
  214.             i += k;
  215.     }
  216.     return;
  217. }
  218. /*********************************************************************
  219. key_create - add a key structure to the table
  220. **********************************************************************/
  221. private
  222. void
  223. key_create(disp, size, seq, rfield, key_type, iflag)
  224. unsigned int
  225.     disp, size, rfield, key_type;
  226. BOOLEAN iflag;
  227. SEQ *seq;
  228. {
  229.     KEY *key_ptr;
  230.  
  231.     if(MAX_KEYS == key_count)
  232.         error("Too many key fields used");
  233.  
  234.     key_ptr = &key[key_count++];
  235.     key_ptr->disp = disp;
  236.     key_ptr->size = size;
  237.     key_ptr->rfield = rfield;
  238.     key_ptr->key_type = key_type;
  239.     key_ptr->inverted = iflag;
  240.     key_ptr->seq = seq;
  241.     return;
  242. }
  243.